home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / TEXTBUFF.C < prev    next >
C/C++ Source or Header  |  1991-12-30  |  9KB  |  307 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * TextBuffer - editable text buffer
  25.  */
  26.  
  27. #include <InterViews/regexp.h>
  28. #include <InterViews/textbuffer.h>
  29. #include <ctype.h>
  30. #include <memory.h>
  31. #include <string.h>
  32.  
  33. static const char NEWLINE = '\012';
  34.  
  35. TextBuffer::TextBuffer (char* t, int l, int s) {
  36.     text = t;
  37.     length = l;
  38.     size = s;
  39.     memset(text + length, '\0', size - length);
  40.     linecount = 1 + LinesBetween(0, length);
  41.     lastline = 0;
  42.     lastindex = 0;
  43. }
  44.  
  45. TextBuffer::~TextBuffer () {
  46.     Text();
  47. }
  48.  
  49. inline int limit (int l, int x, int h) {
  50.     return (x<l) ? l : (x>h) ? h : x;
  51. }
  52.  
  53. int TextBuffer::Search (Regexp* regexp, int index, int range, int stop) {
  54.     int s = limit(0, stop, length);
  55.     int i = limit(0, index, s);
  56.     return regexp->Search(text, s, i, range);
  57. }
  58.  
  59. int TextBuffer::BackwardSearch (Regexp* regexp, int index) {
  60.     int i = limit(0, index, length);
  61.     int r = regexp->Search(text, length, i, -i);
  62.     if (r >= 0) {
  63.         return regexp->BeginningOfMatch();
  64.     } else {
  65.         return r;
  66.     }
  67. }
  68.  
  69. int TextBuffer::ForwardSearch (Regexp* regexp, int index) {
  70.     int i = limit(0, index, length);
  71.     int r = regexp->Search(text, length, i, length - i);
  72.     if (r >= 0) {
  73.     return regexp->EndOfMatch();
  74.     } else {
  75.         return r;
  76.     }
  77. }
  78.  
  79. int TextBuffer::Match (Regexp* regexp, int index, int stop) {
  80.     int s = limit(0, stop, length);
  81.     int i = limit(0, index, s);
  82.     return regexp->Match(text, length, i);
  83. }
  84.  
  85. boolean TextBuffer::BackwardMatch (Regexp* regexp, int index) {
  86.     int i = limit(0, index, length);
  87.     for (int j = i; j >= 0; --j) {
  88.         if (regexp->Match(text, length, j) == i - j) {
  89.             return true;
  90.         }
  91.     }
  92.     return false;
  93. }
  94.  
  95. boolean TextBuffer::ForwardMatch (Regexp* regexp, int index) {
  96.     int i = limit(0, index, length);
  97.     return regexp->Match(text, length, i) >= 0;
  98. }
  99.  
  100. int TextBuffer::Insert (int index, const char* string, int count) {
  101.     if (index < 0 || index > length) {
  102.         return 0;
  103.     } else if (count < 0) {
  104.         return Insert(index + count, string, -count);
  105.     } else {
  106.         count = min(count, size - length);
  107.     memmove(text + index + count, text + index, length - index);
  108.     memmove(text + index, string, count);
  109.         length += count;
  110.         int newlines = (count == 1)
  111.             ? (*string == NEWLINE)
  112.             : LinesBetween(index, index + count);
  113.     linecount += newlines;
  114.         if (lastindex > index) {
  115.             lastindex += count;
  116.         lastline += newlines;
  117.         }
  118.         return count;
  119.     }
  120. }
  121.  
  122. int TextBuffer::Delete (int index, int count) {
  123.     if (index < 0 || index > length) {
  124.         return 0;
  125.     } else if (count < 0) {
  126.         return -Delete(index + count, -count);
  127.     } else {
  128.         count = min(count, length - index);
  129.         int oldlines = (count == 1)
  130.             ? (text[index] == NEWLINE)
  131.             : LinesBetween(index, index + count);
  132.         if (lastindex > index + count) {
  133.         lastindex -= count;
  134.             lastline -= oldlines;
  135.         } else if (lastindex >= index) {
  136.         (void)LineNumber(index);
  137.         }
  138.     memmove(text + index, text + index + count, length - (index+count));
  139.         length -= count;
  140.     memset(text + length, '\0', count);
  141.         linecount -= oldlines;
  142.         return count;
  143.     }
  144. }
  145.  
  146. int TextBuffer::Copy (int index, char* buffer, int count) {
  147.     if (index < 0 || index > length) {
  148.         return 0;
  149.     } else if (count < 0) {
  150.         return Copy(index + count, buffer, -count);
  151.     } else {
  152.         count = min(count, length - index);
  153.     memmove(buffer, text + index, count);
  154.         return count;
  155.     }
  156. }
  157.  
  158. int TextBuffer::Width () {
  159.     int width = 0;
  160.     int i = 0;
  161.     while (i != length) {
  162.         width = max(width, EndOfLine(i) - i);
  163.         i = BeginningOfNextLine(i);
  164.     }
  165.     return width;
  166. }
  167.  
  168. int TextBuffer::LineIndex(int line) {
  169.     int l = (line<0) ? 0 : (line>=linecount) ? linecount-1 : line;
  170.     while (lastline > l) {
  171.         --lastline;
  172.         lastindex = BeginningOfLine(EndOfPreviousLine(lastindex));
  173.     }
  174.     while (lastline < l) {
  175.         ++lastline;
  176.         lastindex = BeginningOfNextLine(lastindex);
  177.     }
  178.     if (line >= linecount) {
  179.         return EndOfText();
  180.     } else {
  181.         return lastindex;
  182.     }
  183. }
  184.  
  185. int TextBuffer::LinesBetween (int index1, int index2) {
  186.     if (index1 == index2) {
  187.         return 0;
  188.     } else if (index1 > index2) {
  189.         return -LinesBetween(index2, index1);
  190.     } else {
  191.         const char* start = Text(index1);
  192.         const char* finish = Text(index2);
  193.         const char* tt;
  194.         int l = 0;
  195.     while (start < finish) {
  196.         tt = (const char*)memchr(start, NEWLINE, finish - start);
  197.         if (tt == nil) {
  198.         break;
  199.         }
  200.         start = tt + 1;
  201.         ++l;
  202.         }
  203.         return l;
  204.     }
  205. }
  206.  
  207. int TextBuffer::LineNumber (int index) {
  208.     int l = LinesBetween(lastindex, index);
  209.     lastline += l;
  210.     lastindex = BeginningOfLine(index);
  211.     return lastline;
  212. }
  213.  
  214. int TextBuffer::LineOffset (int index) {
  215.     return (index<0) ? 0 : (index>length) ? 0 : index-BeginningOfLine(index);
  216. }
  217.  
  218. boolean TextBuffer::IsBeginningOfLine (int index) {
  219.     const char* t = Text(index);
  220.     return t <= text || *(t-1) == NEWLINE;
  221. }
  222.  
  223. int TextBuffer::BeginningOfLine (int index) {
  224.     const char* t = Text(index);
  225.     while (t > text && *(t-1) != NEWLINE) {
  226.         --t;
  227.     }
  228.     return t - text;
  229. }
  230.  
  231. int TextBuffer::BeginningOfNextLine (int index) {
  232.     const char* t = Text(index);
  233.     const char* e = text + length;
  234.     t = (const char*)memchr(t, NEWLINE, e - t);
  235.     if (t == nil) {
  236.         return length;
  237.     } else {
  238.         return t - text + 1;
  239.     }
  240. }
  241.  
  242. boolean TextBuffer::IsEndOfLine (int index) {
  243.     const char* t = Text(index);
  244.     return t >= text + length || *t == NEWLINE;
  245. }
  246.  
  247. int TextBuffer::EndOfLine (int index) {
  248.     const char* t = Text(index);
  249.     const char* e = text + length;
  250.     t = (const char*)memchr(t, NEWLINE, e - t);
  251.     if (t == nil) {
  252.         return length;
  253.     } else {
  254.         return t - text;
  255.     }
  256. }
  257.  
  258. int TextBuffer::EndOfPreviousLine (int index) {
  259.     const char* t = Text(index-1);
  260.     while (t > text && *t != NEWLINE) {
  261.         --t;
  262.     }
  263.     return t - text;
  264. }
  265.  
  266. boolean TextBuffer::IsBeginningOfWord (int index) {
  267.     const char* t = Text(index);
  268.     return t <= text || !isalnum(*(t-1)) && isalnum(*t);
  269. }
  270.  
  271. int TextBuffer::BeginningOfWord (int index) {
  272.     const char* t = Text(index);
  273.     while (t > text && !(!isalnum(*(t-1)) && isalnum(*t))) {
  274.         --t;
  275.     }
  276.     return t - text;
  277. }
  278.  
  279. int TextBuffer::BeginningOfNextWord (int index) {
  280.     const char* t = Text(index+1);
  281.     while (t < text+length && !(!isalnum(*(t-1)) && isalnum(*t))) {
  282.         ++t;
  283.     }
  284.     return t - text;
  285. }
  286.  
  287. boolean TextBuffer::IsEndOfWord (int index) {
  288.     const char* t = Text(index);
  289.     return t >= text+length || isalnum(*(t-1)) && !isalnum(*t);
  290. }
  291.  
  292. int TextBuffer::EndOfWord (int index) {
  293.     const char* t = Text(index);
  294.     while (t < text+length && !(isalnum(*(t-1)) && !isalnum(*t))) {
  295.         ++t;
  296.     }
  297.     return t - text;
  298. }
  299.  
  300. int TextBuffer::EndOfPreviousWord (int index) {
  301.     const char* t = Text(index-1);
  302.     while (t > text && !(isalnum(*(t-1)) && !isalnum(*t))) {
  303.         --t;
  304.     }
  305.     return t - text;
  306. }
  307.